/* This module translates the libc functions to add some control (such as
 * error validation) specific to citymayor. */

#include "fct_translation.h"

#include <errno.h>
#include <stdarg.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sqlite3.h>

#include "global.h"

static void file_error(const char* path)
{
	switch(errno)
	{
		case EACCES:
			ui_error(_("Access denied to %s."), path);
		case EBUSY:
			ui_error(_("File %s in use."), path);
		case EEXIST:
			ui_error(_("File %s already exists."), path);
		case EISDIR:
			ui_error(_("%s is a directory."), path);
		case ENAMETOOLONG:
			ui_error(_("Pathname %s too long."), path);
		case ENOENT:
			ui_error(_("File %s does not exist."), path);
		case ENOSPC:
			ui_error(_("No free space on device when creating %s or writing to a file."), path);
		case ENOTDIR:
			ui_error(_("%s is not a directory."), path);
		case ENXIO:
			ui_error(_("%s is a device special file."), path);
		case EROFS:
			ui_error(_("%s is read only."), path);
		case EPERM:
			ui_error(_("Device does not support the creation of directories."));
		case EBADF:
			ui_error(_("Invalid file."));
		case EIO:
			ui_error(_("Physical disk error."));
		default:
			ui_error(_("Error errno %d in %s"), errno, path);
	}
	abort();
}


// Interface to fopen.
FILE *cm_fopen(const char *path, const char *mode)
{
	FILE *f = fopen(path, mode);
	if(!f)
		file_error(path);

	return f;
}


// Interface to fprintf
int cm_fprintf(FILE *stream, const char *format, ...)
{
	char buffer[4096];

	// create error string
	va_list args;
	va_start(args, format);
	vsprintf(buffer, format, args);
	va_end(args);

	int n = vfprintf(stream, format, args);
	if(!n)
		file_error("");

	return n;
}


#ifdef __MINGW32__
extern int mkdir(const char *, mode_t);
#endif

// Interface to mkdir
int cm_mkdir(const char *pathname, mode_t mode)
{
	int n = mkdir(pathname, mode);
	if(n == -1)
		file_error(pathname);

	return n;
}


// Interface to remove
int cm_remove(const char *pathname)
{
	int n = remove(pathname);
	if(n == -1)
		file_error(pathname);

	return n;
}


// Interface to remove
int cm_rename(const char *oldpath, const char *newpath)
{
	int n = rename(oldpath, newpath);
	if(n == -1)
		file_error(newpath);

	return n;
}


//
// SQLite interface
// 
void sq3_error()
{
	ui_error("SQL error: %s", sqlite3_errmsg(db));
}

void sq3_test(int command)
{
	if(command != SQLITE_OK && command != SQLITE_BUSY
	&& command != SQLITE_DONE && command != SQLITE_ROW
	&& command != SQLITE_ERROR)
		sq3_error();
}
